package com.yunchao.feature.lock.presentation.screen

import androidx.lifecycle.viewModelScope
import com.yunchao.feature.base.data.CustomAudioManager
import com.yunchao.feature.base.domain.result.errorMsg
import com.yunchao.feature.base.presentation.viewmodel.BaseAction
import com.yunchao.feature.base.presentation.viewmodel.BaseEffect
import com.yunchao.feature.base.presentation.viewmodel.BaseState
import com.yunchao.feature.base.presentation.viewmodel.BaseViewModel
import com.yunchao.feature.lock.domain.model.LockInfoModel
import com.yunchao.feature.lock.domain.repository.LockHandleRepository
import com.yunchao.feature.lock.presentation.screen.LockViewModel.Action
import com.yunchao.feature.lock.presentation.screen.LockViewModel.UiEffect
import com.yunchao.feature.lock.presentation.screen.LockViewModel.UiState
import com.yunchao.library.lock.DeviceHelper
import com.yunchao.library.lock.IDeviceHelper
import com.yunchao.library.lock.LockEPCInfo
import kotlinx.coroutines.launch

internal class LockViewModel(
    private val lockHandleRepository: LockHandleRepository,
    private val customAudioManager: CustomAudioManager
) : BaseViewModel<UiState, Action, UiEffect>(
    initialState = UiState.Idle
) {


    fun inventoryOnce() = handleLockOperation { lockHandleRepository.inventoryOnce() }

    fun inventoryOnceAndLogCount() = handleLockOperation { lockHandleRepository.inventoryOnceAndLogCount() }

    fun openLock(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.openLock(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2,
            pageNumber = 0
        )
    }

    fun closeLock(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.closeLock(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2,
            pageNumber = 0
        )
    }


    fun openLockLogistics(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.openLockLogistics(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2,
            pageNumber = 0
        )
    }

    fun closeLockLogistics(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.closeLockLogistics(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2,
            pageNumber = 0
        )
    }


    fun cleanLock(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.cleanLock(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2,
            pageNumber = lockEPCInfo.pageNumber
        )
    }


    fun recoveryLock(lockEPCInfo: LockEPCInfo) = handleLockOperation {
        lockHandleRepository.recoveryLock(
            lockEPCInfo = lockEPCInfo,
            deviceId = IDeviceHelper.DEFAULT_DEVICE_ID,
            operatorId = IDeviceHelper.DEFAULT_OPERATOR_1,
            chkUserId = IDeviceHelper.DEFAULT_OPERATOR_2
        )
    }

    fun readLockLogistics() = handleLockOperation { lockHandleRepository.readLockLogistics() }


    fun readLockLog(lockEPCInfo: LockEPCInfo, start: Int, number: Int = 2) = handleLockOperation {
        lockHandleRepository.readLockLog(lockEPCInfo, start, number)
    }

    private fun handleLockOperation(operation: suspend () -> Result<LockInfoModel>) =
        viewModelScope.launch {
            postSideEffect(UiEffect.ShowLoading)
            operation().onSuccess {
                sendAction(Action.LockHandleSuccess(it))
                    .apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(1) }
            }.onFailure {
                postSideEffect(UiEffect.ShowToast(it.errorMsg))
                    .apply { postSideEffect(UiEffect.HideLoading) }
                    .apply { customAudioManager.playSound(2) }
            }
        }


    internal sealed interface Action : BaseAction<UiState> {
        class LockHandleSuccess(private val lockInfoModel: LockInfoModel) : Action {
            override fun reduce(state: UiState) = UiState.Success(lockInfoModel)
        }
    }

    internal sealed interface UiState : BaseState {
        data class Success(val lockInfoModel: LockInfoModel) : UiState
        data object Idle : UiState
    }

    internal sealed interface UiEffect : BaseEffect {
        data object ShowLoading : UiEffect
        data object HideLoading : UiEffect
        data class ShowToast(val msg: String) : UiEffect
    }
}